/*
 * TOSEApp.cpp
 *
 * This file is a part of TermOSEmulator.
 *
 * Written by Peter Winchester <wincsoft_pw@outlook.com>
 * Copyright (C) 2021 Peter Winchester.
 *
 * TermOSEmulator is free software, follows the GNU General
 * Public License.
 *
 * NOTE: TermOSEmulator requires Windows API, so it can only
 * run on the Windows.
 *
 */

#include "TOSEApp.h"

int numApplications;
char dir[MAX_STRING_LEN];
char installPath[MAX_STRING_LEN];
Application apps[MAX_NUM_APPLICAITONS];

//启动一个app
int startApplication(int hApp)
{
    string dir; //用于存储app的地址
    for (int i = 0; i < strlen(systemRootPath); i++)
    {
        dir.push_back(systemRootPath[i]);
    }
    dir += "etc/";
    dir += apps[hApp].name;
    dir += ".exe";
	
    /* 检查可执行文件是否存在 */
    FILE *ftest = fopen(dir.c_str(), "rb");
    if (ftest == NULL)
    {
        printf("Can't find the executable file on Windows.\n");
        return 0;
    }
    fclose(ftest);
    int res = system(dir.c_str()); //启动
    return res == 0;
}

//安装app
int installApp()
{
    /* 输入可执行文件路径 */
    printf("Please type the path of the executable file:\n");
    memset(dir, 0, sizeof(dir));
    gets(dir); //将路径储存在dir里

    /* 检查路径是否合法 */
    FILE *fin = fopen(dir, "rb");
    if (fin == NULL) //找不到指定文件
    {
        printf("The executable file doesn't exist.\n");
        return 0;
    }

    string exeFileName, exeName, exeType;

    /* 获取可执行文件名 */
    int pos = strlen(dir) - 1;
    while (pos >= 0 && dir[pos] != '/')
        pos--; //找到dir中最后一个'/'字符
    /* dir的最后一个'/'之后的部分即文件名 */
    for (int i = pos + 1; i < strlen(dir); i++)
    {
        exeFileName.push_back(dir[i]);
    }

    /* 获取安装目录 */
    memset(installPath, 0, sizeof(installPath));
    strcat(installPath, systemRootPath);
    strcat(installPath, "etc/");
    strcat(installPath, exeFileName.c_str());
    FILE *fout = fopen(installPath, "wb"); //检查安装目录是否合法
    if (fout == NULL)
    {
        printf("Cannot install the app, please check the directory /etc.\n");
        fclose(fin);
        return 0;
    }

    /* 获取文件类型 */
    for (int i = exeFileName.length() - 1; i >= 0; i--)
    {
        /* 文件名的最后一个'.'字符之后就是文件类型 */
        if (exeFileName[i] == '.')
        {
            for (int j = i + 1; j < exeFileName.length(); j++)
            {
                exeType.push_back(exeFileName[j]);
            }
            break;
        }
    }
    if (exeType != "exe") //文件类型错误
    {
        printf("The type of executable file must be exe.\n");
        return 0;
    }

    /* 定位到/etc目录 */
    Directory *dirPos = dirCrt;
    while (dirPos->name != "root")
        dirPos = dirPos->dirFather;
    for (int i = 0; i < dirPos->dirChild.size(); i++)
    {
        if (dirPos->dirChild[i]->name == "etc")
        {
            dirPos = dirPos->dirChild[i];
            break;
        }
    }

    /* 获取可执行文件名称 */
    for (int i = exeFileName.length() - 1; i >= 0; i--)
    {
        //exeFileName最后一个'.'前面的部分就是文件名称
        if (exeFileName[i] == '.')
        {
            for (int j = 0; j < i; j++)
            {
                exeName.push_back(exeFileName[j]);
            }
        }
    }

    /* 检查这个app之前是否被安装过，避免重复安装 */
    for (int i = 0; i < numApplications; i++)
    {
        if (apps[i].name == exeName) //已经被安装过了
        {
            if (fin) fclose(fin);
            if (fout) fclose(fout);
            printf("The app has been installed.\n");
            return 0;
        }
    }

    /* 安装应用程序 */
    char cGet;
    while (fscanf(fin, "%c", &cGet) == 1) fprintf(fout, "%c", cGet); //复制可执行文件
    fclose(fin);
    fclose(fout);
    TOSEFile tmp;
    tmp.name = exeName, tmp.type = exeType;
    dirPos->file.push_back(tmp); //将可执行文件添加至 TOSE 资源管理器
    apps[numApplications++].name = exeName;
    updateExplorer(); //更新资源管理器的数据
    updateAppData();

    printf("Installed.\n");
    return 1;
}

//移除app
int removeApp()
{
    printf("Please type the name of the app which you want to remove:\n");
    string nameReq;
    cin >> nameReq;

    /* 查找输入的app */
    bool find = false;
    for (int i = 0; i < numApplications; i++)
    {
        if (apps[i].name == nameReq)
        {
            find = true;
            break;
        }
    }
    if (!find) //未找到该app
    {
        printf("Cannot find the typed app.\n");
        return 0;
    }

    /* 在TermOSEmulator里删除相应的可执行文件 */
    string typeReq = "exe";
    Directory *dirPos = dirRoot, *dirTmp = dirCrt;
    for (int i = 0; i < dirPos->dirChild.size(); i++)
    {
        if (dirPos->dirChild[i]->name == "etc")
        {
            dirPos = dirPos->dirChild[i];
        }
    }
    dirCrt = dirPos;
    removeFile(nameReq, typeReq);
    dirCrt = dirTmp;

    /* 在Windows上移除对应的可执行文件 */
    string dir;
    for (int i = 0; i < strlen(systemRootPath); i++)
    {
        dir.push_back(systemRootPath[i]);
    }
    dir += "etc/";
    dir += nameReq;
    dir += ".exe";
    FILE *ftest = fopen(dir.c_str(), "rb");
    if (ftest != NULL)
    {
        fclose(ftest);
        string cmd = "del \"";
        cmd += dir;
        cmd += "\"";
        for (int i = 0; i < cmd.length(); i++)
        {
            if (cmd[i] == '/')
            {
                cmd[i] = '\\';
            }
        }
        system(cmd.c_str());
    }

    /* 更新数据 */
    for (int i = 0; i < numApplications; i++)
    {
        if (apps[i].name == nameReq)
        {
            for (int j = i; j < numApplications - 1; j++)
            {
                apps[j] = apps[j + 1];
            }
            break;
        }
    }
    numApplications--;
    updateAppData();

    printf("Removed.\n");
    return 1;
}

//检测不需要的app并移除
int autoRemove()
{
	char path[MAX_STRING_LEN];
	for (int i = 0; i < numApplications; i++)
	{
		sprintf(path, "../etc/%s.exe", apps[i].name.c_str());
		FILE *fin = fopen(path, "rb");
		if (fin == NULL)
		{
			for (int j = i; j < numApplications - 1; j++) apps[j] = apps[j + 1];
			numApplications--;
		}
		else fclose(fin);
	}
	updateAppData(); //更新数据
	return 1;
}

//更新应用程序数据
void updateAppData()
{
    ofstream fout;
    fout.open("../dat/sysappdat.txt", ios::out);
    fout << numApplications << endl;
    for (int i = 0; i < numApplications; i++)
    {
        fout << apps[i].name << endl;
    }
    fout.close();
}

//列出所有已安装的app
int listApps()
{
    if (numApplications == 0)
	{
		printf("No installed application.\n");
		return 1;
	}
	printf("%d applications installed:\n", numApplications);
	for (int i = 0; i < numApplications; i++)
	{
		cout << apps[i].name << ' ';
	}
	cout << endl;
	return 1;
}
